package com.example.fileupload.controller;

import com.example.fileupload.dto.ApiResponse;
import com.example.fileupload.dto.HealthCheckResult;
import com.example.fileupload.storage.StorageStrategy;
import com.example.fileupload.storage.StorageStrategyFactory;
import com.example.fileupload.util.StorageHealthChecker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 存储管理控制器 - 提供存储策略信息和管理功能
 */
@Slf4j
@RestController
@RequestMapping("/storage")
public class StorageManagementController {
    
    @Autowired
    private StorageStrategyFactory storageStrategyFactory;
    
    @Autowired
    private StorageHealthChecker healthChecker;
    
    /**
     * 获取当前默认存储策略信息
     */
    @GetMapping("/current")
    public ApiResponse<StorageInfo> getCurrentStrategy() {
        try {
            StorageStrategy strategy = storageStrategyFactory.getDefaultStrategy();
            return ApiResponse.success(StorageInfo.of(strategy));
        } catch (Exception e) {
            log.error("获取当前存储策略失败: {}", e.getMessage());
            return ApiResponse.error("获取当前存储策略失败");
        }
    }
    
    /**
     * 获取所有可用的存储策略
     */
    @GetMapping("/strategies")
    public ApiResponse<Map<String, StorageInfo>> getAllStrategies() {
        try {
            Map<String, StorageInfo> strategies = storageStrategyFactory.getAllStrategies()
                    .entrySet()
                    .stream()
                    .collect(Collectors.toMap(
                            entry -> entry.getKey().getValue(),
                            entry -> StorageInfo.of(entry.getValue())
                    ));
            return ApiResponse.success(strategies);
        } catch (Exception e) {
            log.error("获取存储策略列表失败: {}", e.getMessage());
            return ApiResponse.error("获取存储策略列表失败");
        }
    }
    
    /**
     * 检查指定存储策略是否可用
     */
    @GetMapping("/check/{storageType}")
    public ApiResponse<Boolean> checkStrategy(@PathVariable String storageType) {
        try {
            boolean available = storageStrategyFactory.isStrategyAvailable(storageType);
            return ApiResponse.success(available);
        } catch (Exception e) {
            log.error("检查存储策略失败: {}", e.getMessage());
            return ApiResponse.error("检查存储策略失败");
        }
    }
    
    /**
     * 测试存储策略连接
     */
    @PostMapping("/test/{storageType}")
    public ApiResponse<String> testStrategy(@PathVariable String storageType) {
        return healthChecker.checkStorageHealth(storageType)
                .map(result -> ApiResponse.success(result.getMessage()))
                .orElse(ApiResponse.error("测试存储策略失败"));
    }
    
    /**
     * 获取详细的健康检查结果
     */
    @GetMapping("/health/{storageType}")
    public ApiResponse<HealthCheckResult> getHealthDetail(@PathVariable String storageType) {
        return healthChecker.getCachedHealth(storageType, 60000) // 1分钟缓存
                .map(ApiResponse::success)
                .orElse(ApiResponse.error("获取健康状态失败"));
    }
    
    /**
     * 获取所有存储策略的健康状态
     */
    @GetMapping("/health")
    public CompletableFuture<ApiResponse<Map<String, HealthCheckResult>>> getAllHealthStatus() {
        return healthChecker.checkAllStoragesAsync()
                .thenApply(ApiResponse::success)
                .exceptionally(throwable -> ApiResponse.error("获取健康状态失败: " + throwable.getMessage()));
    }
    
    /**
     * 存储策略信息DTO
     */
    public static class StorageInfo {
        private String type;
        private String className;
        private boolean available;
        private long timestamp;
        
        public StorageInfo() {}
        
        public StorageInfo(String type, String className, boolean available) {
            this.type = type;
            this.className = className;
            this.available = available;
            this.timestamp = System.currentTimeMillis();
        }
        
        public static StorageInfo of(StorageStrategy strategy) {
            return new StorageInfo(
                    strategy.getStorageType().getValue(),
                    strategy.getClass().getSimpleName(),
                    true
            );
        }
        
        // Getters and Setters
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getClassName() { return className; }
        public void setClassName(String className) { this.className = className; }
        
        public boolean isAvailable() { return available; }
        public void setAvailable(boolean available) { this.available = available; }
        
        public long getTimestamp() { return timestamp; }
        public void setTimestamp(long timestamp) { this.timestamp = timestamp; }
    }
} 